package spass.scene;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import spass.geometry.Point;
import spass.geometry.Ray;
import spass.renderer.Color;
import spass.scene.forms.Intersection;
import spass.scene.light.DirectionalLight;

public class CompositeSceneObject implements SceneObject {

    private final List<SceneObject> components;

    public CompositeSceneObject(SceneObject... components) {
        this.components = Arrays.asList(components);
    }

    @Override
    public Intersection closestIntersection(Ray ray) {
        List<Intersection> intersections = collectIntersections(ray, components);

        if (intersections.isEmpty()) {
            return null; // FIXME dont make null part of the contract
        }

        Intersection closestIntersection = scanIntersectionsForLeastDistance(intersections, ray.getOrigin());

        return closestIntersection;
    }

    private List<Intersection> collectIntersections(Ray ray, Collection<SceneObject> objects) {
        List<Intersection> intersections = new ArrayList<Intersection>();

        for (SceneObject object : objects) {
            Intersection intersection = object.closestIntersection(ray);
            if (intersection != null) {
                intersections.add(intersection);
            }
        }

        return intersections;
    }

    private Intersection scanIntersectionsForLeastDistance(List<Intersection> intersections, Point origin) {
        Double leastDistance = null;
        Intersection closestIntersection = null;

        for (Intersection intersection : intersections) {
            Point intersectionPoint = intersection.getPoint();
            double distance = origin.distanceTo(intersectionPoint);

            if (leastDistance == null || distance < leastDistance) {
                leastDistance = distance;
                closestIntersection = intersection;
            }
        }

        return closestIntersection;
    }

    @Override
    public Color colorInDirectionalLightAt(Intersection intersection, DirectionalLight directionalLight) {
        SceneObject object = intersection.getObject();

        return object.colorInDirectionalLightAt(intersection, directionalLight); // FIXME move to Intersection
    }

    //    public static CompositeSceneObject simpleTree(Point position, double diameter) {
    //        Vector axis = new Vector(0, diameter, 0);
    //
    //        Cylinder cylinder = new Cylinder(position, axis, diameter / 10);
    //        ColoredForm trunk = new ColoredForm(cylinder, new Color(0.6, 0.3, 0.2));
    //
    //        Sphere sphere = new Sphere(axis, diameter / 2);
    //        ColoredForm crown = new ColoredForm(sphere, new Color(0.1, 0.5, 0.1));
    //
    //        return new CompositeSceneObject(trunk, crown);
    //    }
}
